from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.utils.translation import gettext_lazy as _


class SubjectForm(forms.ModelForm):
    """科目表单"""

    class Meta:
        from .models import Subject
        model = Subject
        fields = ['name', 'full_score', 'color', 'order']
        widgets = {
            'color': forms.TextInput(attrs={'type': 'color', 'class': 'form-control form-control-color'}),
            'full_score': forms.NumberInput(attrs={'step': 0.5, 'min': 0, 'class': 'form-control'}),
            'order': forms.NumberInput(attrs={'min': 0, 'class': 'form-control'}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
        }


class ExamTypeForm(forms.ModelForm):
    """考试类型表单"""

    class Meta:
        from .models import ExamType
        model = ExamType
        fields = ['name', 'description']
        widgets = {
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'description': forms.Textarea(
                attrs={'rows': 3, 'class': 'form-control', 'placeholder': '简要描述该考试类型的特点或适用场景'}),
        }


class ExamForm(forms.ModelForm):
    """考试表单 - 更新为使用 base_name 和 sequence_number"""

    class Meta:
        from .models import Exam
        model = Exam
        fields = ['base_name', 'sequence_number', 'exam_type', 'exam_date', 'description', 'total_score',
                  'difficulty_level']
        widgets = {
            'base_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：历年真题、张宇八套卷'}),
            'sequence_number': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '如：2006、6'}),
            'exam_type': forms.Select(attrs={'class': 'form-select'}),
            'exam_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'description': forms.Textarea(
                attrs={'rows': 3, 'class': 'form-control', 'placeholder': '可填写考试范围、注意事项等信息'}),
            'total_score': forms.NumberInput(attrs={'step': 0.5, 'min': 0, 'class': 'form-control'}),
            'difficulty_level': forms.NumberInput(attrs={'step': 0.1, 'min': 0, 'max': 1, 'class': 'form-control',
                                                         'placeholder': '0-1之间，数字越大难度越高'}),
        }

    def clean(self):
        cleaned_data = super().clean()
        from .models import Exam
        base_name = cleaned_data.get('base_name')
        sequence_number = cleaned_data.get('sequence_number')

        # 验证基础名称和序号的组合是否唯一
        if base_name and sequence_number is not None:
            if Exam.objects.filter(base_name=base_name, sequence_number=sequence_number).exists():
                if not self.instance.pk:  # 新建时才检查
                    raise ValidationError('该考试名称和序号的组合已存在')

        return cleaned_data


class ExamRecordForm(forms.ModelForm):
    """考试成绩记录表单 - 考研专用版本"""

    # 关键修复：将 exam 和 subject 字段设置为非必填，在 clean 方法中手动验证
    exam = forms.ModelChoiceField(
        queryset=None,  # 改为 None，在 __init__ 中设置
        required=False,  # 关键修复：设置为非必填
        label="选择考试",
        widget=forms.Select(attrs={
            'class': 'form-select',
            'id': 'id_exam'
        })
    )

    subject = forms.ChoiceField(
        choices=[],  # 会在 __init__ 中设置
        required=False,  # 关键修复：设置为非必填
        label="考试科目",
        widget=forms.Select(attrs={
            'class': 'form-select',
            'id': 'id_subject'
        })
    )

    # 自定义考试字段 - 现在拆分为基础名称和序号
    custom_exam_base_name = forms.CharField(
        max_length=100,
        required=False,
        label="考试基础名称",
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '输入考试基础名称...',
            'id': 'id_custom_exam_base_name'
        })
    )

    custom_exam_sequence = forms.IntegerField(
        required=False,
        label="序号",
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'placeholder': '输入序号...',
            'id': 'id_custom_exam_sequence'
        })
    )

    exam_date = forms.DateField(
        required=False,
        label="考试日期",
        widget=forms.DateInput(attrs={
            'type': 'date',
            'class': 'form-control',
            'id': 'id_exam_date'
        })
    )

    # 考研相关字段
    target_score = forms.FloatField(
        required=False,
        label="理想分数",
        widget=forms.NumberInput(attrs={
            'step': 0.5,
            'min': 0,
            'class': 'form-control',
            'placeholder': '期望达到的分数',
            'id': 'id_target_score'
        })
    )

    time_management = forms.ChoiceField(
        required=False,
        label="时间管理",
        choices=[
            ('', '请选择'),
            ('excellent', '时间充足'),
            ('good', '时间刚好'),
            ('tight', '时间紧张'),
            ('insufficient', '时间不足')
        ],
        widget=forms.Select(attrs={
            'class': 'form-select',
            'id': 'id_time_management'
        })
    )

    question_completion = forms.FloatField(
        required=False,
        label="题目完成度",
        widget=forms.NumberInput(attrs={
            'step': 1,
            'min': 0,
            'max': 100,
            'class': 'form-control',
            'placeholder': '0-100%',
            'id': 'id_question_completion'
        })
    )

    # 修改后的难度系数字段：0-10之间，步长0.1
    difficulty_level = forms.FloatField(
        required=False,
        label="难度系数",
        widget=forms.NumberInput(attrs={
            'step': 0.1,
            'min': 0,
            'max': 10,
            'class': 'form-control',
            'placeholder': '0-10之间，数字越大难度越高',
            'id': 'id_difficulty_level'
        })
    )

    class Meta:
        from .models import ExamRecord
        model = ExamRecord
        # 关键修复：添加所有新字段到 fields 列表中
        fields = [
            'exam', 'subject', 'score', 'exam_duration', 'exam_status',
            'target_score', 'question_completion', 'difficulty_level', 'time_management'
        ]
        widgets = {
            'score': forms.NumberInput(attrs={
                'step': 0.5,
                'min': 0,
                'class': 'form-control',
                'id': 'id_score'
            }),
            'exam_duration': forms.NumberInput(attrs={
                'min': 0,
                'class': 'form-control',
                'placeholder': '分钟',
                'id': 'id_exam_duration'
            }),
            'exam_status': forms.Select(attrs={
                'class': 'form-select',
                'id': 'id_exam_status'
            }),
            # 关键修复：为新字段添加 widgets（可选，因为已经在字段定义中设置了）
            'target_score': forms.NumberInput(attrs={
                'step': 0.5,
                'min': 0,
                'class': 'form-control',
                'placeholder': '期望达到的分数',
                'id': 'id_target_score'
            }),
            'question_completion': forms.NumberInput(attrs={
                'step': 1,
                'min': 0,
                'max': 100,
                'class': 'form-control',
                'placeholder': '0-100%',
                'id': 'id_question_completion'
            }),
            'difficulty_level': forms.NumberInput(attrs={
                'step': 0.1,
                'min': 0,
                'max': 10,
                'class': 'form-control',
                'placeholder': '0-10之间，数字越大难度越高',
                'id': 'id_difficulty_level'
            }),
            'time_management': forms.Select(attrs={
                'class': 'form-select',
                'id': 'id_time_management'
            }),
        }

    def __init__(self, *args, **kwargs):
        from .models import Exam, Subject
        self.student = kwargs.pop('student', None)
        super().__init__(*args, **kwargs)

        # 初始化 exam 字段的 queryset
        if not self.fields['exam'].queryset:
            self.fields['exam'].queryset = Exam.objects.none()

        # 考试字段：只显示当前学生参加过的考试
        try:
            if self.student:
                # 只获取该学生参加过的所有考试
                student_exams = Exam.objects.filter(
                    records__student=self.student
                ).distinct().order_by('-exam_date')

                # 为下拉框创建选项：只显示基础名称
                exam_choices = [('', '选择已有考试或输入新考试')]
                for exam in student_exams:
                    exam_choices.append((exam.id, exam.base_name))

                self.fields['exam'].choices = exam_choices
                self.fields['exam'].queryset = student_exams
                print(f"DEBUG - 为学生 {self.student.name} 加载了 {len(student_exams)} 个考试")
            else:
                # 管理员模式：显示空的选择，因为管理员需要先选择学生
                self.fields['exam'].choices = [('', '请先选择学生')]
                self.fields['exam'].queryset = Exam.objects.none()
                print("DEBUG - 管理员模式，考试选择为空")
        except Exception as e:
            # 如果查询出错，显示空的查询集
            print(f"考试查询错误: {e}")
            self.fields['exam'].choices = [('', '选择已有考试或输入新考试')]
            self.fields['exam'].queryset = Exam.objects.none()

        # 科目字段：从用户配置生成科目选项
        try:
            if self.student:
                # 从学生配置中获取科目列表
                subject_choices = []

                # 政治科目
                if self.student.has_politics:
                    subject_choices.append(('政治', '政治'))

                # 英语科目
                if self.student.has_english and self.student.english_type != '不考':
                    subject_choices.append((self.student.english_type, self.student.english_type))

                # 数学科目
                if self.student.has_math and self.student.math_type != '不考':
                    subject_choices.append((self.student.math_type, self.student.math_type))

                # 专业课一
                if self.student.professional_subject_name:
                    subject_choices.append(
                        (self.student.professional_subject_name, self.student.professional_subject_name))

                # 专业课二
                if self.student.has_professional_2 and self.student.professional_subject_2_name:
                    subject_choices.append(
                        (self.student.professional_subject_2_name, self.student.professional_subject_2_name))

                print(f"DEBUG - 用户科目配置: {subject_choices}")

                # 设置科目选择
                self.fields['subject'].choices = [('', '请选择科目')] + subject_choices
            else:
                # 管理员模式：显示所有可能的科目
                all_subjects = Subject.objects.all()
                if all_subjects.exists():
                    subject_choices = [(s.name, s.name) for s in all_subjects]
                else:
                    # 如果没有Subject数据，使用默认科目
                    subject_choices = [
                        ('政治', '政治'),
                        ('英语一', '英语一'),
                        ('英语二', '英语二'),
                        ('数学一', '数学一'),
                        ('数学二', '数学二'),
                        ('数学三', '数学三'),
                        ('专业课一', '专业课一'),
                        ('专业课二', '专业课二'),
                    ]

                self.fields['subject'].choices = [('', '请选择科目')] + subject_choices

        except Exception as e:
            print(f"科目配置错误: {e}")
            # 如果出错，使用默认科目
            self.fields['subject'].choices = [('', '请选择科目'), ('政治', '政治'), ('英语一', '英语一')]

        # 关键修复：为所有字段添加ID以确保JavaScript能正常工作
        for field_name, field in self.fields.items():
            if 'id' not in field.widget.attrs:
                field.widget.attrs['id'] = f'id_{field_name}'

        # 关键修复：为新字段设置占位符和合理的默认值
        self.fields['target_score'].widget.attrs['placeholder'] = '期望达到的分数（可选）'
        self.fields['question_completion'].widget.attrs['placeholder'] = '0-100（可选）'
        self.fields['difficulty_level'].widget.attrs['placeholder'] = '0-10之间（可选）'

        # 设置一些合理的默认值（只在添加模式且没有实例时）
        if not self.instance.pk:
            self.fields['question_completion'].initial = 100  # 默认100%完成
            self.fields['difficulty_level'].initial = 5.0  # 默认中等难度

        # 关键修复：完全移除所有disabled设置，让JavaScript控制
        # 编辑模式下也不设置disabled，通过JavaScript来控制
        if self.instance and self.instance.pk:
            print("编辑模式：所有字段初始可用，由JavaScript控制状态")
            # 编辑模式下，我们不在Django层面设置disabled，让JavaScript处理
            # 这样可以避免HTML渲染时设置disabled属性
        else:
            # 添加模式：所有字段初始都可用，不要设置disabled属性
            # 让JavaScript在页面加载后控制字段状态
            print("添加模式：所有字段初始可用，由JavaScript控制状态")

            # 特别确保自定义考试字段没有disabled属性
            custom_fields = ['custom_exam_base_name', 'custom_exam_sequence', 'exam_date']
            for field_name in custom_fields:
                if field_name in self.fields:
                    # 移除可能存在的disabled属性
                    if 'disabled' in self.fields[field_name].widget.attrs:
                        del self.fields[field_name].widget.attrs['disabled']

    def clean(self):
        from .models import Subject, ExamRecord, Exam
        cleaned_data = super().clean()

        # 修复：只在表单提交时进行完整验证
        if not self.data:
            return cleaned_data

        # 获取所有提交的字段名（排除csrf token）
        submitted_fields = [key for key in self.data.keys() if key != 'csrfmiddlewaretoken']

        # 如果没有实际提交的表单数据，说明是页面初次加载，跳过验证
        if not submitted_fields:
            return cleaned_data

        # 检查是否是表单提交（有实际数据且不是页面加载）
        is_form_submission = any(value for key, value in self.data.items()
                                 if key != 'csrfmiddlewaretoken' and value)

        # 如果不是表单提交，跳过验证
        if not is_form_submission:
            return cleaned_data

        # 以下是实际的表单验证逻辑（只在提交时执行）
        exam = cleaned_data.get('exam')
        custom_exam_base_name = cleaned_data.get('custom_exam_base_name', '').strip()
        custom_exam_sequence = cleaned_data.get('custom_exam_sequence')
        exam_date = cleaned_data.get('exam_date')
        subject_name = cleaned_data.get('subject')
        score = cleaned_data.get('score')
        exam_duration = cleaned_data.get('exam_duration')
        target_score = cleaned_data.get('target_score')
        question_completion = cleaned_data.get('question_completion')
        difficulty_level = cleaned_data.get('difficulty_level')

        print(f"DEBUG - 表单提交验证: 科目={subject_name}, 考试={exam}, 自定义考试={custom_exam_base_name}")

        # 关键修复：编辑模式下跳过考试信息二选一验证
        is_edit_mode = bool(self.instance and self.instance.pk)

        if not is_edit_mode:
            # 只在添加模式下验证考试信息二选一逻辑
            has_existing_exam = bool(exam)
            has_custom_exam = bool(custom_exam_base_name)

            if not has_existing_exam and not has_custom_exam:
                # 如果两者都没有，显示错误
                raise forms.ValidationError("请选择已有考试或输入新的考试名称")

            if has_existing_exam and has_custom_exam:
                # 如果两者都有值，显示错误
                self.add_error('exam', '不能同时选择已有考试和输入新考试名称')
                self.add_error('custom_exam_base_name', '不能同时选择已有考试和输入新考试名称')

            # 关键修复：如果输入新考试，必须填写基础名称、序号和考试日期
            if has_custom_exam and not has_existing_exam:
                if not custom_exam_sequence:
                    self.add_error('custom_exam_sequence', '输入新考试时必须填写序号')
                if custom_exam_sequence is not None and custom_exam_sequence < 0:
                    self.add_error('custom_exam_sequence', '序号不能为负数')
                if not exam_date:
                    self.add_error('exam_date', '输入新考试时必须填写考试日期')
        else:
            # 编辑模式下：确保考试日期有值
            if not exam_date:
                self.add_error('exam_date', '考试日期不能为空')

        # 关键修复：验证科目必须存在
        if not subject_name:
            self.add_error('subject', '请选择科目')
        else:
            # 根据科目名称获取或创建Subject对象
            try:
                subject, created = Subject.objects.get_or_create(
                    name=subject_name,
                    defaults={
                        'full_score': 150,
                        'color': '#3498db',
                        'order': 1
                    }
                )
                cleaned_data['subject'] = subject
                if created:
                    print(f"自动创建科目: {subject_name}")
            except Exception as e:
                self.add_error('subject', f'科目处理失败: {e}')

        # 关键修复：验证分数必填且不超过科目满分
        if score is None:
            self.add_error('score', '请输入分数')
        elif 'subject' in cleaned_data:
            subject_obj = cleaned_data['subject']
            if score < 0:
                self.add_error('score', '分数不能为负数')
            elif score > subject_obj.full_score:
                self.add_error('score', f'分数不能超过科目满分({subject_obj.full_score}分)')

        # 验证考试时长
        if exam_duration is not None and exam_duration < 0:
            self.add_error('exam_duration', '考试时长不能为负数')

        # 验证目标分数
        if target_score is not None and 'subject' in cleaned_data:
            subject_obj = cleaned_data['subject']
            if target_score < 0:
                self.add_error('target_score', '目标分数不能为负数')
            elif target_score > subject_obj.full_score:
                self.add_error('target_score', f'目标分数不能超过科目满分({subject_obj.full_score}分)')

        # 验证题目完成度
        if question_completion is not None:
            if question_completion < 0 or question_completion > 100:
                self.add_error('question_completion', '题目完成度必须在0-100之间')

        # 验证难度系数 - 修改为0-10之间
        if difficulty_level is not None:
            if difficulty_level < 0 or difficulty_level > 10:
                self.add_error('difficulty_level', '难度系数必须在0-10之间')

        # 验证重复记录 - 只在选择已有考试时检查（添加模式）
        if exam and 'subject' in cleaned_data and self.student and not self.instance.pk:
            try:
                if ExamRecord.objects.filter(student=self.student, exam=exam, subject=cleaned_data['subject']).exists():
                    self.add_error(None, '该考试科目已存在成绩记录')
            except Exception as e:
                print(f"重复记录检查错误: {e}")

        return cleaned_data

    def save(self, commit=True):
        from .models import Exam
        # 先获取实例但不保存
        exam_record = super().save(commit=False)

        # 处理自定义考试创建（只在添加模式下）
        custom_exam_base_name = self.cleaned_data.get('custom_exam_base_name', '').strip()
        custom_exam_sequence = self.cleaned_data.get('custom_exam_sequence')
        exam_date = self.cleaned_data.get('exam_date')

        # 关键修复：编辑模式下不创建新考试，只更新考试日期
        if self.instance and self.instance.pk:
            # 编辑模式：更新考试日期
            if exam_date and exam_record.exam:
                exam_record.exam.exam_date = exam_date
                exam_record.exam.save()
        else:
            # 添加模式：处理自定义考试创建
            if custom_exam_base_name and custom_exam_sequence is not None and exam_date:
                try:
                    # 检查是否已存在相同基础名称和序号的考试
                    existing_exam = Exam.objects.filter(
                        base_name=custom_exam_base_name,
                        sequence_number=custom_exam_sequence
                    ).first()

                    if existing_exam:
                        # 使用已存在的考试
                        exam_record.exam = existing_exam
                    else:
                        # 创建新的考试
                        difficulty_level = self.cleaned_data.get('difficulty_level', 5.0)
                        exam = Exam.objects.create(
                            base_name=custom_exam_base_name,
                            sequence_number=custom_exam_sequence,
                            exam_date=exam_date,
                            total_score=150,
                            difficulty_level=difficulty_level
                        )
                        exam_record.exam = exam
                except Exception as e:
                    raise forms.ValidationError(f"创建考试失败: {e}")

        # 设置学生
        if self.student:
            exam_record.student = self.student

        if commit:
            exam_record.save()

        return exam_record


class KnowledgePointForm(forms.ModelForm):
    """知识点表单"""

    class Meta:
        from .models import KnowledgePoint
        model = KnowledgePoint
        fields = ['subject', 'name', 'parent', 'weight', 'order']
        widgets = {
            'subject': forms.Select(attrs={'class': 'form-select'}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'parent': forms.Select(attrs={'class': 'form-select'}),
            'weight': forms.NumberInput(
                attrs={'step': 0.1, 'min': 0, 'class': 'form-control', 'placeholder': '数值越大表示越重要'}),
            'order': forms.NumberInput(attrs={'min': 0, 'class': 'form-control', 'placeholder': '用于排序显示'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        from .models import KnowledgePoint
        # 添加空选项提示
        self.fields['parent'].empty_label = "无（顶级知识点）"

        # 优化父级知识点过滤逻辑
        if self.instance and self.instance.pk:
            # 排除自身作为父级
            self.fields['parent'].queryset = KnowledgePoint.objects.filter(
                subject=self.instance.subject
            ).exclude(pk=self.instance.pk).order_by('order', 'name')
        elif 'subject' in self.data:
            try:
                subject_id = int(self.data.get('subject'))
                self.fields['parent'].queryset = KnowledgePoint.objects.filter(
                    subject_id=subject_id
                ).order_by('order', 'name')
            except (ValueError, TypeError):
                pass  # 无效ID时不修改查询集

    def clean(self):
        cleaned_data = super().clean()
        subject = cleaned_data.get('subject')
        parent = cleaned_data.get('parent')

        # 验证父级知识点必须与当前知识点同属一个科目
        if parent and parent.subject != subject:
            raise forms.ValidationError("父级知识点必须与当前知识点属于同一科目")

        return cleaned_data


class ScoreLossDetailForm(forms.ModelForm):
    """失分明细编辑表单"""

    class Meta:
        from .models import ScoreLossDetail
        model = ScoreLossDetail
        fields = [
            'loss_type', 'knowledge_point', 'custom_knowledge_point',
            'points', 'question_number', 'description',
            'is_understand', 'review_date'
        ]
        widgets = {
            'review_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'description': forms.Textarea(attrs={'rows': 3, 'class': 'form-control'}),
            'loss_type': forms.Select(attrs={'class': 'form-select'}),
            'knowledge_point': forms.Select(attrs={'class': 'form-select'}),
            'custom_knowledge_point': forms.TextInput(attrs={'class': 'form-control'}),
            'points': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.5'}),
            'question_number': forms.TextInput(attrs={'class': 'form-control'}),
        }

    def __init__(self, *args, **kwargs):
        from .models import KnowledgePoint
        # 接收 exam_record 参数（用于权限验证和知识点创建）
        self.exam_record = kwargs.pop('exam_record', None)
        super().__init__(*args, **kwargs)

        # 初始值处理：自定义知识点优先显示
        instance = kwargs.get('instance')
        if instance and instance.custom_knowledge_point:
            # 当有自定义知识点时，清空下拉选择框
            self.fields['knowledge_point'].initial = None

        # 知识点下拉框仅显示当前科目的知识点
        if self.exam_record:
            self.fields['knowledge_point'].queryset = KnowledgePoint.objects.filter(
                subject=self.exam_record.subject
            ).order_by('order')
        else:
            self.fields['knowledge_point'].queryset = KnowledgePoint.objects.all().order_by('subject__order', 'order')

        # 字段标签优化
        self.fields['loss_type'].label = '失分类型'
        self.fields['knowledge_point'].label = '涉及知识点（可选）'
        self.fields['custom_knowledge_point'].label = '自定义知识点（可选）'
        self.fields['points'].label = '失分分值'
        self.fields['question_number'].label = '题号'
        self.fields['description'].label = '失分描述'
        self.fields['is_understand'].label = '是否已掌握'
        self.fields['review_date'].label = '计划复习日期'

    def clean(self):
        """表单级验证：处理知识点逻辑冲突"""
        cleaned_data = super().clean()
        knowledge_point = cleaned_data.get('knowledge_point')
        custom_knowledge_point = cleaned_data.get('custom_knowledge_point', '').strip()
        points = cleaned_data.get('points')

        # 1. 知识点验证：必须选择系统知识点或输入自定义知识点
        if not knowledge_point and not custom_knowledge_point:
            raise ValidationError(_('请选择系统知识点或输入自定义知识点'))

        # 2. 知识点互斥验证：不能同时选择系统知识点和输入自定义知识点
        if knowledge_point and custom_knowledge_point:
            raise ValidationError(_('不能同时选择系统知识点和输入自定义知识点'))

        # 3. 失分分值验证（结合科目满分）
        if points is not None and self.exam_record:
            max_allowed_loss = self.exam_record.subject.full_score
            if points <= 0:
                raise ValidationError(_('失分分值必须大于0'))
            if points > max_allowed_loss:
                raise ValidationError(_(f'失分分值不能超过科目满分（{max_allowed_loss}分）'))

        # 4. 自定义知识点格式验证
        if custom_knowledge_point:
            if len(custom_knowledge_point) > 100:
                raise ValidationError(_('自定义知识点名称不能超过100个字符'))
            # 清空系统知识点选择（避免Model层验证冲突）
            cleaned_data['knowledge_point'] = None

        return cleaned_data

    def save(self, commit=True):
        """重写保存方法：处理自定义知识点创建逻辑"""
        from .models import KnowledgePoint
        # 获取清洁后的数据
        custom_knowledge_point = self.cleaned_data.get('custom_knowledge_point', '').strip()

        # 先获取实例（不立即保存到数据库）
        loss_detail = super().save(commit=False)

        # 关联考试记录（确保数据完整性）
        if self.exam_record:
            loss_detail.exam_record = self.exam_record

        # 处理自定义知识点创建
        if custom_knowledge_point and self.exam_record:
            # 使用get_or_create避免重复创建相同名称的知识点
            knowledge_point, created = KnowledgePoint.objects.get_or_create(
                subject=self.exam_record.subject,
                name=custom_knowledge_point,
                defaults={
                    'is_custom': True,
                    'created_by': self.exam_record.student,
                    'weight': 1.0,
                    'order': 999  # 自定义知识点默认排在最后
                }
            )
            # 关联新创建的知识点
            loss_detail.knowledge_point = knowledge_point
            # 🔴 关键修复：清空自定义知识点字段（避免Model层验证冲突）
            loss_detail.custom_knowledge_point = ""
            # 同步更新cleaned_data（保持数据一致性）
            self.cleaned_data['custom_knowledge_point'] = ""

        # 最终保存（触发Model验证前已确保数据合规）
        if commit:
            loss_detail.save()

        return loss_detail